package util

import (
	"bytes"
	"crypto/cipher"
	"crypto/des"
	"crypto/rand"
	_ "fmt"
	"io"
)

func DesEncrypt(plainText, key []byte) (cipherText []byte, err error) {
	block, err := des.NewCipher(key)
	if err != nil {
		return nil, err
	}
	origData := pkcs5padding(plainText, block.BlockSize())
	cipherText = make([]byte, block.BlockSize()+len(origData))
	iv := cipherText[:block.BlockSize()]
	if _, err := io.ReadFull(rand.Reader, iv); err != nil {
		panic(err)
	}

	blockMode := cipher.NewCBCEncrypter(block, iv)
	blockMode.CryptBlocks(cipherText[block.BlockSize():], origData)
	return
}

func DesDecrypt(cipherText, key []byte) (plainText []byte, err error) {
	block, err := des.NewCipher(key)
	if err != nil {
		return
	}

	iv := cipherText[:block.BlockSize()]
	cipherText = cipherText[block.BlockSize():]
	blockMode := cipher.NewCBCDecrypter(block, iv)
	blockMode.CryptBlocks(cipherText, cipherText)
	plainText = pkcs5unpadding(cipherText)
	return
}

func pkcs5padding(plainText []byte, blockSize int) []byte {
	padding := blockSize - len(plainText)%blockSize
	paddingText := bytes.Repeat([]byte{byte(padding)}, padding)
	return append(plainText, paddingText...)
}

func pkcs5unpadding(origData []byte) []byte {
	length := len(origData)
	unpadding := int(origData[length-1])
	return origData[:(length - unpadding)]
}
